﻿#include "stdafx.h"
#include "skinheader.h"
#include "HeaderSkin.h"

#define HDI_SUPPORTED_FIELDS (HDI_WIDTH|HDI_TEXT|HDI_FORMAT|HDI_LPARAM|HDI_BITMAP|HDI_IMAGE|HDI_ORDER)
CSkinHeader::CSkinHeader(void)
{
	//m_pHeaderSkin = GetSkin().GetHeaderSkin();
	m_nHotItem = -1;
	m_nPressedItem = -1;
}

CSkinHeader::~CSkinHeader(void)
{
	HookWindow( (HWND)NULL);
}
BOOL CSkinHeader::InstallSkin(HWND hWnd)
{
    if (!hWnd || !LoadSkin())
    {
        return FALSE;
    }
	m_bEnableSkin = TRUE;
	HookWindow( (HWND)NULL);

	int r = HookWindow( hWnd );


	m_pHeaderSkin = GetSkin().GetHeaderSkin();
	if(m_pHeaderSkin == NULL)
		m_bEnableSkin = FALSE;

#ifdef _WIN64
	LONG_PTR style = GetWindowLongPtr(m_hWnd, GWL_STYLE);
	LONG_PTR exstyle = GetWindowLongPtr(m_hWnd, GWL_EXSTYLE);
#else
	DWORD style = GetWindowLong(m_hWnd, GWL_STYLE);
	DWORD exstyle = GetWindowLong(m_hWnd, GWL_EXSTYLE);
#endif

	SetWindowPos(m_hWnd,NULL, 0, 0, 0, 0,  SWP_FRAMECHANGED|SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER); 
    return TRUE;
}
BOOL CSkinHeader::LoadSkin()
{
    CAutoEnableSkin a(m_bEnableSkin);
	m_pHeaderSkin = GetSkin().GetHeaderSkin();
    if (!m_pHeaderSkin)
        return FALSE;
	SetWindowPos(m_hWnd,NULL, 0, 0, 0, 0, SWP_FRAMECHANGED | SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER); 
    return TRUE;
}
LRESULT CSkinHeader::OnWndMsg(UINT msg,WPARAM wp,LPARAM lp)
{
	switch(msg)
	{
	case WM_MOUSELEAVE:
		OnMouseLeave();
		return 0;
	}
	return CSkinWnd::OnWndMsg(msg,wp,lp);
}

void CSkinHeader::OnPaint()
{
//	Default();
	CHeaderCtrl *pHeader = (CHeaderCtrl*)CWnd::FromHandle(m_hWnd);
	CPaintDC dc(pHeader);
	CRect rtClient;
	GetClientRect(rtClient);
	CMemDC menDC(&dc,rtClient);
//	Default(WM_PAINT,(WPARAM)dc.m_hDC,0);
	DrawHeader(&menDC);
	
}
BOOL CSkinHeader::OnEraseBkgnd(CDC* pDC)
{
	return TRUE;
}
void CSkinHeader::OnMouseMove( UINT nFlags, const CPoint& point )
{
	Default();
	if((nFlags & MK_LBUTTON) == 0)
	{
		TRACKMOUSEEVENT tme;
		m_nHotItem = HitTest(point);
		m_nPressedItem = -1;
		tme.cbSize = sizeof(TRACKMOUSEEVENT);
		tme.dwFlags = TME_LEAVE;
		tme.hwndTrack = m_hWnd;
		TrackMouseEvent(&tme);
	}
	else if(nFlags & MK_LBUTTON)
	{
		TRACKMOUSEEVENT tme;
		m_nPressedItem = HitTest(point);
		m_nHotItem = -1;
		tme.cbSize = sizeof(TRACKMOUSEEVENT);
		tme.dwFlags = TME_LEAVE;
		tme.hwndTrack = m_hWnd;
		TrackMouseEvent(&tme);
	}
	CHeaderCtrl *pHeader = (CHeaderCtrl*)CWnd::FromHandle(m_hWnd);
    CAutoReleaseDC pDC(reinterpret_cast<CWnd*>(pHeader));
	pDC =  pHeader->GetDC();
	CRect rtClient;
	GetClientRect(rtClient);
	CMemDC dc(pDC,rtClient);
	DrawHeader(&dc);
}
void CSkinHeader::OnLButtonDown( UINT nFlags, const CPoint& point )
{
	Default();
	m_nPressedItem = HitTest(point);
	m_nHotItem = -1;
	CHeaderCtrl *pHeader = (CHeaderCtrl*)CWnd::FromHandle(m_hWnd);
    CAutoReleaseDC pDC(reinterpret_cast<CWnd*>(pHeader));
	pDC =  pHeader->GetDC();
	CRect rtClient;
	GetClientRect(rtClient);
	CMemDC dc(pDC,rtClient);
	DrawHeader(&dc);
}
void CSkinHeader::OnMouseLeave()
{
	m_nHotItem = -1;
	m_nPressedItem = -1;
	CHeaderCtrl *pHeader = (CHeaderCtrl*)CWnd::FromHandle(m_hWnd);
    CAutoReleaseDC pDC(reinterpret_cast<CWnd*>(pHeader));
	pDC =  pHeader->GetDC();
	CRect rtClient;
	GetClientRect(rtClient);
	CMemDC dc(pDC,rtClient);
	DrawHeader(&dc);
}
void CSkinHeader::OnLButtonUp( UINT nFlags, const CPoint& point )
{
	Default();
	m_nPressedItem = -1;
	m_nHotItem = HitTest(point);
	CHeaderCtrl *pHeader = (CHeaderCtrl*)CWnd::FromHandle(m_hWnd);
    CAutoReleaseDC pDC(reinterpret_cast<CWnd*>(pHeader));
	pDC =  pHeader->GetDC();
	CRect rtClient;
	GetClientRect(rtClient);
	CMemDC dc(pDC,rtClient);
	DrawHeader(&dc);
}
UINT CSkinHeader::HitTest( const CPoint& point )
{
	CHeaderCtrl *pHeader = (CHeaderCtrl*)CWnd::FromHandle(m_hWnd);
	int nCount = pHeader->GetItemCount();
	CRect rtItem;
	for(int i = 0 ; i < nCount ; i++)
	{
		pHeader->GetItemRect(i,rtItem);
		if(rtItem.PtInRect(point))
			return i;
	}
	return -1;
}
void CSkinHeader::DrawHeader(CDC *pDC)
{
	CRect rtClient;
	GetClientRect(rtClient);
	CHeaderCtrl *pHeader = (CHeaderCtrl*)CWnd::FromHandle(m_hWnd);
	m_pHeaderSkin->DrawImageSection(pDC,rtClient,m_pHeaderSkin->m_imageBackground);
	int nCount = pHeader->GetItemCount();
	CRect rtItem;
	for(int i = 0 ; i < nCount ; i++)
	{
		pHeader->GetItemRect(i,rtItem);
		if(m_nPressedItem == i)
			DrawItemEntry(pDC,i,rtItem,PRESSED);
		else if(m_nHotItem == i)
			DrawItemEntry(pDC,i,rtItem,HOVER);
		else
			DrawItemEntry(pDC,i,rtItem,NORMAL);
//		m_pHeaderSkin->DrawImageSection()
	}
}
void CSkinHeader::DrawItemEntry( CDC* pDC, int nIndex, const CRect& rcItem, int nState )
{
	if(nState == PRESSED)
	{
		if(!m_pHeaderSkin->DrawImageSection(pDC,rcItem,m_pHeaderSkin->m_imageItemPressed))
			m_pHeaderSkin->DrawImageSection(pDC,rcItem,m_pHeaderSkin->m_imageItemNormal);
	}
	else if(nState == HOVER)
	{
		if(!m_pHeaderSkin->DrawImageSection(pDC,rcItem,m_pHeaderSkin->m_imageItemHover))
			m_pHeaderSkin->DrawImageSection(pDC,rcItem,m_pHeaderSkin->m_imageItemNormal);
	}
	else
	{
		m_pHeaderSkin->DrawImageSection(pDC,rcItem,m_pHeaderSkin->m_imageItemNormal);
	}


	TCHAR buf[256];
	HD_ITEM hItem;
	ZeroMemory(&hItem,sizeof(hItem));
	hItem.mask = HDI_SUPPORTED_FIELDS;
	hItem.pszText = buf;
	hItem.cchTextMax = 255;

	CHeaderCtrl *pHeader = (CHeaderCtrl*)CWnd::FromHandle(m_hWnd);
	pHeader->GetItem(nIndex,&hItem);

	CImageList *pImageList = pHeader->GetImageList();

	//int cxIcon,cyIcon;
	//ImageList_GetIconSize(hImageList,&cxIcon,&cyIcon);

	UINT rw, rh, *x = NULL, *w = NULL; 
	UINT cx, tx, ix, bx,
		cw, tw, iw, bw;
	BITMAP bmp;

	cw = tw = iw = bw = 0;
	rw = rcItem.Width();
	rh = rcItem.Height();

	if (hItem.fmt & HDF_STRING)
	{
		RECT textRect;

		SetRectEmpty(&textRect);
		pDC->DrawText ( hItem.pszText, -1,
			&textRect, DT_LEFT|DT_VCENTER|DT_SINGLELINE|DT_CALCRECT);
		cw = textRect.right - textRect.left + 2 * 3*GetSystemMetrics(SM_CXEDGE);
	}

	//if ((hItem.fmt & HDF_IMAGE) && (hImageList)) 
	//{
	//	iw = cxIcon + 2 *GetSystemMetrics(SM_CXEDGE);
	//	x = &ix;
	//	w = &iw;
	//}

	//if ((hItem.fmt & HDF_BITMAP) && (hItem.hbm))
	//{
	//	GetObject (hItem.hbm, sizeof(BITMAP), (LPVOID)&bmp);
	//	bw = bmp.bmWidth + 2 * GetSystemMetrics(SM_CXEDGE);
	//	if (!iw) 
	//	{
	//		x = &bx;
	//		w = &bw;
	//	}
	//}

	//if (bw || iw)
	//	cw += *w; 

	///* align cx using the unclipped cw */
	//if ((hItem.fmt & HDF_JUSTIFYMASK) == HDF_LEFT)
	//	cx = rcItem.left;
	//else if ((hItem.fmt & HDF_JUSTIFYMASK) == HDF_CENTER)
	//	cx = rcItem.left + rw / 2 - cw / 2;
	//else /* HDF_RIGHT */
	//	cx = rcItem.right - cw;

	///* clip cx & cw */
	//if (cx < rcItem.left)
	//	cx = rcItem.left;
	//if (cx + cw > rcItem.right)
	//	cw = rcItem.right - cx;

	//tx = cx + GetSystemMetrics(SM_CXEDGE);
	///* since cw might have changed we have to recalculate tw */
	//tw = cw - GetSystemMetrics(SM_CXEDGE)* 2;

	//if (iw || bw) 
	//{
	//	tw -= *w;
	//	if (hItem.fmt & HDF_BITMAP_ON_RIGHT) 
	//		*x = cx + tw + GetSystemMetrics(SM_CXEDGE) * 3;
	//	else 
	//	{
	//		*x = cx + GetSystemMetrics(SM_CXEDGE);
	//		/* move text behind pic */
	//		tx += *w;
	//	}
	//}

	//if (iw && bw) 
	//{
	//	if ((hItem.fmt & HDF_JUSTIFYMASK) == HDF_RIGHT)
	//		bx = cx - bw + GetSystemMetrics(SM_CXEDGE);
	//	else
	//		bx = cx + cw + GetSystemMetrics(SM_CXEDGE);
	//}

	//if (iw || bw) 
	//{
	//	HDC hClipDC = GetDC(m_hWnd);
	//	HRGN hClipRgn = CreateRectRgn(rcItem.left, rcItem.top, rcItem.right, rcItem.bottom);
	//	SelectClipRgn(hClipDC, hClipRgn);

	//	if (bw) 
	//	{
	//		HDC hdcBitmap = CreateCompatibleDC (hClipDC);
	//		SelectObject (hdcBitmap, hItem.hbm);
	//		BitBlt (hClipDC, bx, rcItem.top + ((INT)rh - bmp.bmHeight) / 2, 
	//			bmp.bmWidth, bmp.bmHeight, hdcBitmap, 0, 0, SRCCOPY);
	//		DeleteDC (hdcBitmap);
	//	}

	//	if (iw) 
	//	{
	//		ImageList_DrawEx (hImageList, hItem.iImage, hClipDC, 
	//			ix, rcItem.top + ((INT)rh - cyIcon) / 2,
	//			cxIcon, cyIcon, CLR_DEFAULT, CLR_DEFAULT, 0);
	//	}

	//	DeleteObject(hClipRgn);
	//	ReleaseDC(m_hWnd, hClipDC);
	//}

	UINT uFormat = DT_SINGLELINE | DT_NOPREFIX | DT_VCENTER | DT_END_ELLIPSIS ;

	CRect rtText(&rcItem);
	if((hItem.fmt & HDF_RIGHT) == HDF_RIGHT)
	{
		rtText.right -= 6;
		uFormat |= DT_RIGHT;
	}
	else if((hItem.fmt & HDF_CENTER) == HDF_CENTER)
		uFormat |= DT_CENTER;
	else
	{
		rtText.left += 6;
		uFormat |= DT_LEFT;
	}
	
	CFont *pFont = pHeader->GetFont();
	CFont *pOld = pDC->SelectObject(pFont);
	int oldBkMode = pDC->SetBkMode(TRANSPARENT);
	pDC->DrawText(buf, &rtText, uFormat);	
	if (oldBkMode != TRANSPARENT)
		pDC->SetBkMode(oldBkMode);
	pDC->SelectObject(pOld);

	//if (((hItem.fmt & HDF_STRING)
	//	|| (!(hItem.fmt & (HDF_OWNERDRAW|HDF_STRING|HDF_BITMAP|
	//	HDF_BITMAP_ON_RIGHT|HDF_IMAGE)))) /* no explicit format specified? */
	//	&& (hItem.pszText)) 
	//{
	//		int oldBkMode = pDC->SetBkMode(TRANSPARENT);
	//	//	rcItem.left  = tx;
	//	//	rcItem.right = tx + tw;
	//		pDC->DrawText( hItem.pszText,-1,
	//			&rcItem, DT_LEFT|DT_END_ELLIPSIS|DT_VCENTER|DT_SINGLELINE);
	//		if (oldBkMode != TRANSPARENT)
	//			pDC->SetBkMode(oldBkMode);
	//}


}